// File: jmcomic-core/src/main/java/dev/jukomu/common/base/logger/AbstractSetLogger.java
package dev.jukomu.common.base.logger;

import java.io.IOException;
import java.util.Collection;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 对应Python的AbstractSetLogger，为基于Set的Logger提供通用实现。
 *
 * @param <E> 记录器中元素的类型
 */
public abstract class AbstractSetLogger<E> implements Logger<E> {

    protected Set<E> data; // 内部Set，用于存储记录的元素

    public AbstractSetLogger() {
        this.data = null; // 延迟加载
    }

    @Override
    public boolean isDone(E element) {
        makeSureLoaded();
        return data.contains(element);
    }

    @Override
    public void add(E element, boolean save) throws IOException {
        makeSureLoaded();
        data.add(element);
        if (save) {
            save();
        }
    }

    @Override
    public void addAll(Collection<E> elements, boolean save) throws IOException {
        makeSureLoaded();
        data.addAll(elements);
        if (save) {
            save();
        }
    }

    @Override
    public int size() {
        makeSureLoaded();
        return data.size();
    }

    @Override
    public void remove(E element, boolean save) throws IOException {
        makeSureLoaded();
        if (data.remove(element) && save) { // remove returns true if element was present
            save();
        }
    }

    @Override
    public void setData(Set<E> data) {
        this.data = data;
    }

    @Override
    public Set<E> getData() {
        makeSureLoaded();
        return data;
    }

    @Override
    public void clearData() {
        // 使用ConcurrentHashMap.newKeySet()来确保线程安全，即使清空后也能安全地添加元素
        this.data = ConcurrentHashMap.newKeySet();
    }

    @Override
    public void makeSureLoaded() {
        if (data == null) {
            try {
                load();
            } catch (IOException e) {
                // 包装IOException为RuntimeException，因为makeSureLoaded不声明IOException
                // 这意味着如果加载失败，程序会崩溃，符合Python中没有try-catch时的行为
                throw new RuntimeException("Failed to load logger data.", e);
            }
        }
    }

    @Override
    public Iterator<E> iterator() {
        makeSureLoaded();
        return data.iterator();
    }

    @Override
    public boolean contains(E element) {
        return isDone(element);
    }

    @Override
    public String toString() {
        return "AbstractSetLogger{" +
                "size=" + size() +
                ", loaded=" + (data != null) +
                '}';
    }
}